﻿using System;
using System.Collections.Generic;

namespace UnityModule
{
    /// <summary>
    /// 引用池管理器
    /// </summary>
    public static class ReferencePoolManager
    {
        private static readonly IDictionary<string, ReferencePool> s_ReferencePools = new Dictionary<string, ReferencePool>();

        /// <summary>
        /// 获取引用池的数量。
        /// </summary>
        public static int PoolCount
        {
            get
            {
                return s_ReferencePools.Count;
            }
        }

        /// <summary>
        /// 获取所有引用池的信息。
        /// </summary>
        /// <returns>所有引用池的信息。</returns>
        public static ReferencePoolInfo[] GetAllReferencePoolInfos()
        {
            int index = 0;
            ReferencePoolInfo[] results = null;

            //lock (s_ReferencePools)
            {
                results = new ReferencePoolInfo[s_ReferencePools.Count];
                foreach (KeyValuePair<string, ReferencePool> referenceCollection in s_ReferencePools)
                {
                    results[index++] = referenceCollection.Value.PoolInfo;
                }
            }

            return results;
        }

        public static ReferencePoolInfo GetReferencePoolInfo(Type type)
        {
            ReferencePool pool;
            if(s_ReferencePools.TryGetValue(type.FullName, out pool))
            {
                return pool.PoolInfo;
            }
            return null;
        }

        public static ReferencePoolInfo GetReferencePoolInfo<T>() where T : class, IReference
        {
            return GetReferencePoolInfo(typeof(T));
        }

        /// <summary>
        /// 清除所有引用池。
        /// </summary>
        public static void ClearAll()
        {
           // lock (s_ReferencePools)
            {
                foreach (KeyValuePair<string, ReferencePool> referenceCollection in s_ReferencePools)
                {
                    referenceCollection.Value.RemoveAll();
                }

                s_ReferencePools.Clear();
            }
        }

        /// <summary>
        /// 从引用池获取引用。
        /// </summary>
        /// <typeparam name="T">引用类型。</typeparam>
        public static T Get<T>() where T : class, IReference, new()
        {
            return GetReferencePool(typeof(T)).Get<T>();
        }


        /// <summary>
        /// 当你把构造限制成private时,可以传一个Create 回调
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="createFunc"></param>
        /// <returns></returns>
        public static T Get<T>(Func<IReference> createFunc) where T : class, IReference
        {
            return GetReferencePool(typeof(T)).Get<T>(createFunc);
        }


        /// <summary>
        /// 将引用归还引用池。
        /// </summary>
        /// <param name="reference">引用。</param>
        public static void Release(IReference reference)
        {
            if (null == reference)
            {
                P.E("reference回收Release : 是null");
                return;
            }

            Type referenceType = reference.GetType();
            GetReferencePool(referenceType).Release(reference);
        }

        /// <summary>
        /// 向引用池中追加指定数量的引用。
        /// </summary>
        /// <typeparam name="T">引用类型。</typeparam>
        /// <param name="count">追加数量。</param>
        public static void Add<T>(int count) where T : class, IReference, new()
        {
            GetReferencePool(typeof(T)).Add<T>(count);
        }

        /// <summary>
        /// 向引用池中追加指定数量的引用。 性能稍差
        /// </summary>
        /// <param name="referenceType">引用类型。</param>
        /// <param name="count">追加数量。</param>
        public static void Add(Type referenceType, int count)
        {
            GetReferencePool(referenceType).Add(count);
        }

        /// <summary>
        /// 从引用池中移除指定数量的引用。
        /// </summary>
        /// <typeparam name="T">引用类型。</typeparam>
        /// <param name="count">移除数量。</param>
        public static void Remove<T>(int count) where T : class, IReference
        {
            GetReferencePool(typeof(T)).Remove(count);
        }

        /// <summary>
        /// 从引用池中移除指定数量的引用。
        /// </summary>
        /// <param name="referenceType">引用类型。</param>
        /// <param name="count">移除数量。</param>
        public static void Remove(Type referenceType, int count)
        {
            GetReferencePool(referenceType).Remove(count);
        }

        /// <summary>
        /// 从引用池中移除所有的引用。
        /// </summary>
        /// <typeparam name="T">引用类型。</typeparam>
        public static void RemoveAll<T>() where T : class, IReference
        {
            GetReferencePool(typeof(T)).RemoveAll();
        }

        /// <summary>
        /// 从引用池中移除所有的引用。
        /// </summary>
        /// <param name="referenceType">引用类型。</param>
        public static void RemoveAll(Type referenceType)
        {
            GetReferencePool(referenceType).RemoveAll();
        }


        private static ReferencePool GetReferencePool(Type referenceType)
        {
            string fullName = referenceType.FullName;
            ReferencePool pool = null;
           // lock (s_ReferencePools)
            {
                if (!s_ReferencePools.TryGetValue(fullName, out pool))
                {
                    pool = new ReferencePool(referenceType);
                    s_ReferencePools.Add(fullName, pool);
                    if(referenceType is INeedDestroy)
                    {
                        pool.PoolInfo.IsNeedDisposeType = true;
                    }
                    else
                    {
                        pool.PoolInfo.IsNeedDisposeType = false;
                    }
                }
            }
            return pool;
        }
    }
}
